package com.nectech.entity;

import com.nectech.client.MapleStoryClient;
import com.nectech.constant.Constant;
import com.nectech.util.ImageUtil;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.Random;

/**
 * @Author 浅小北
 * @ClassName Hero
 * @Description 英雄类
 * @Date 2021/1/27 10:23
 * @Since version-1.0
 */
public class Hero extends AbstractMapleStoryObject{
    /**
     * 英雄人物所有图片的加载
     */
    public static Image[] imgs = new Image[100];
    static {
        //左边站
        for (int i = 0; i < 4; i++) {
            imgs[i] = ImageUtil.getImage("hero_left_stand_" + i);
        }
        //右边站
        for (int i = 4; i < 8; i++) {
            imgs[i] = ImageUtil.getImage("hero_right_stand_" + (i - 4));
        }
        //左边走
        for (int i = 8; i < 13; i++) {
            imgs[i] = ImageUtil.getImage("hero_left_walk_" + (i - 8));
        }
        //右边走
        for (int i = 13; i < 18; i++) {
            imgs[i] = ImageUtil.getImage("hero_right_walk_" + (i - 13));
        }
        //左边趴
        imgs[18] = ImageUtil.getImage("hero_left_prone");
        //右边趴
        imgs[19] = ImageUtil.getImage("hero_right_prone");
        //左边跳
        imgs[20] = ImageUtil.getImage("hero_left_jump");
        //右边跳
        imgs[21] = ImageUtil.getImage("hero_right_jump");
        //左边射箭
        for (int i = 22; i < 26; i++) {
            imgs[i] = ImageUtil.getImage("hero_left_shoot_" + (i - 22));
        }
        //右边射箭
        for (int i = 26; i < 30; i++) {
            imgs[i] = ImageUtil.getImage("hero_right_shoot_" + (i - 26));
        }
        //人物血条
        imgs[30] = ImageUtil.getImage("person_blood");
        //人物蓝条
        imgs[31] = ImageUtil.getImage("person_bluemp");
        //人物经验条
        imgs[32] = ImageUtil.getImage("person_purpleexp");
        //人物爬行图片
        imgs[33] = ImageUtil.getImage("hero_climb");
    }
    //无参构造
    public Hero(){}
    /**
     * 创建一个msc对象，利用了中介者模式，也叫做调停者模式
     * 有参构造方法
     */

    public MapleStoryClient msc;
    public Random random = new Random();
    public int MAX_HP = 1000;
    public int MAX_MP = 1000;
    public int MAX_EXP = 1000;
    public int ATT;
    public int hitValue;
    public int MP;
    public int HP;
    public int EXP;
    public Hero(MapleStoryClient msc,int x,int y){
        this.msc = msc;
        this.x = x;
        this.y = y;
        this.MP = MAX_MP;
        this.HP = MAX_HP;
        this.EXP = 0;
        this.ATT = 1000;
        this.height = imgs[0].getHeight(null);
        this.width = imgs[0].getWidth(null);
        this.speed = Constant.WALK_SPEED;
        this.action = Action.STAND;
        this.dir = Direction.RIGHT;
    }

    private int count = 0;
    private int step = 0;
    public boolean left,right,down,jump,shoot,pickUp,climb;
     /**
      * @Author: 浅小北
      * @Description: 重写draw方法，利用开关，switch判定动作
      * @Date: 19:51 2021/1/27
      * @Param: g
      * @return: void
      */
    @Override
    public void draw(Graphics g) {
        switch (dir) {
            case LEFT:
                switch (action) {
                    case STAND:
                        if (count++ % 3 == 0) {
                            g.drawImage(imgs[step++ % 4],x,y,null);
                        } else {
                            g.drawImage(imgs[step % 4],x,y,null);
                        }
                        break;
                    case WALK:
                        if (count++ % 3 == 0) {
                            g.drawImage(imgs[(step++ % 5) + 8],x,y,null);
                        } else {
                            g.drawImage(imgs[(step % 5) + 8],x,y,null);
                        }
                        break;
                    case PRONE:
                        g.drawImage(imgs[18],x + 10,y + 32,null);
                        break;
                    case JUMP:
                        g.drawImage(imgs[20],x,y,null);
                        break;
                    case CLIMB:
                        g.drawImage(imgs[33],x,y,null);
                        break;
                    case SHOOT:
                        if (count++ % 3 == 0) {
                            g.drawImage(imgs[(step++ % 4) + 22],x,y,null);
                        } else {
                            g.drawImage(imgs[(step % 4) + 22],x,y,null);
                        }
                        break;
                    default:
                        break;
                }
                break;
            case RIGHT:
                switch (action) {
                    case STAND:
                        if (count++ % 3 == 0) {
                            g.drawImage(imgs[step++ % 4 + 4],x,y,null);
                        } else {
                            g.drawImage(imgs[step % 4 + 4],x,y,null);
                        }
                        break;
                    case WALK:
                        if (count++ % 3 == 0) {
                            g.drawImage(imgs[(step++ % 5) + 13],x,y,null);
                        } else {
                            g.drawImage(imgs[(step % 5) + 13],x,y,null);
                        }
                        break;
                    case PRONE:
                        g.drawImage(imgs[19],x + 10,y + 32,null);
                        break;
                    case JUMP:
                        g.drawImage(imgs[21],x,y,null);
                        break;
                    case CLIMB:
                        g.drawImage(imgs[33],x,y,null);
                        break;
                    case SHOOT:
                        if (count++ % 3 == 0) {
                            g.drawImage(imgs[(step++ % 4) + 26],x,y,null);
                        } else {
                            g.drawImage(imgs[(step % 4) + 26],x,y,null);
                        }
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
        move();
        drawBlood(g);
        drawBlueMp(g);
        drawPurpleExp(g);
    }

     /**
      * @Author: 浅小北
      * @Description: 画血条
      * @Date: 9:58 2021/2/2
      * @Param:
      * @return:
      */

     public void drawBlood(Graphics g) {
         int n = 104 * this.HP / this.MAX_HP / 10;
         for (int i = 0; i < n; i++) {
             g.drawImage(imgs[30],222 + i * 10,982,null);
         }
     }

      /**
       * @Author: 浅小北
       * @Description: 画人物蓝条
       * @Date: 10:54 2021/2/2
       * @Param:
       * @return:
       */
      public void drawBlueMp(Graphics g) {
          int n = 104 * this.MP / this.MAX_MP / 10;
          for (int i = 0; i < n; i++) {
              g.drawImage(imgs[31],330 + i * 10,982,null);
          }
      }


       /**
        * @Author: 浅小北
        * @Description: 画人物经验条
        * @Date: 11:03 2021/2/2
        * @Param:
        * @return:
        */

       public void drawPurpleExp(Graphics g) {
           int n = 104 * this.EXP / this.MAX_EXP / 10;
           for (int i = 0; i < n; i++) {
               g.drawImage(imgs[32],441 + i * 10,982,null);
           }
       }


     /**
      * @Author: 浅小北
      * @Description: 确定运动动作
      * @Date: 20:12 2021/1/27
      * @Param:
      * @return:
      */
    @Override
    public void move() {
        if (left) {
            x -= speed;
            this.action = Action.WALK;
        }
        if (right) {
            x += speed;
            this.action = Action.WALK;
        }
        if (jump) {
            //调用jump方法
            jump(msc.groundList);
        } else {
            if (climb) {
                if (climb(msc.ladderList)) {
                    drop = false;
                    this.action = Action.CLIMB;
                    y -= 5;
                    //System.out.println(y);
                }

            } else {
                jumpDown(msc.groundList);
            }

        }
        if (shoot) {
            //调用shoot方法
            shoot();
        }
        if (pickUp) {
            //调用shoot方法
            pickUp(msc.propList);
        }
        /*if (climb) {
            //爬行的方法
            climb(msc.ladderList);
        }*/


        outOfBound();
        confirmStatus();
    }

     /**
      * @Author: 浅小北
      * @Description: 人物出界问题的判断
      * @Date: 18:34 2021/1/28
      * @Param:
      * @return:
      */
     public void outOfBound() {
         if (x >= Constant.WINDOW_WIDTH - this.width) {
             this.x = Constant.WINDOW_WIDTH - this.width;
         }
         if (x <= 0) {
             this.x = 0;
         }
         if (this.dir == Direction.LEFT) {
             if (this.x <= 462 && this.y >= 525 - this.height + 50 &&  this.x >= 0) {
                 this.x = 462;
             }
             if (this.x <= 642 && this.y >= 586 - this.height + 50  && this.x >= 462) {
                 this.x = 642;
             }
             if (this.x <= 642 && this.y >= 586 - this.height + 50  && this.x >= 462) {
                 this.x = 642;
             }

         }
         if (this.dir == Direction.RIGHT) {
             if (this.x >= 1730 - this.width && this.y >= 711 - this.height + 50) {
                 this.x = 1730 - this.width;
             }
             if (this.x >= 1813 - this.width && this.y >= 655 - this.height + 50 ) {
                 this.x = 1813 - this.width;
             }
             if (this.x >= 1380 - this.width && this.y >= 402 - this.height + 50
                    && this.x <= 1813 - this.width && this.y <= 576 - this.height + 50) {
                 this.x = 1380 - this.width;
             }
         }
     }
     /**
      * @Author: 浅小北
      * @Description: jump跳的方法
      * @Date: 20:14 2021/1/27
      * @Param:
      * @return:
      */
     private double v0 = Constant.HERO_JUMP_SPEED;
     private double g = 9.8;
     private double vt;
     private double delta_height;
     private double t = 0.7;

     public void jump(List<Ground> groundList) {
         if (!drop) {
             vt = v0 - g * t;
             delta_height = v0 * t;
             v0 = vt;
             y -= delta_height;
             //什么时候往下掉
             if (vt <= 0) {
                 vt = 0;
                 drop = true;
             }
         } else {
             jumpDown(groundList);
         }
     }

      /**
       * @Author: 浅小北
       * @Description: 自由落体的方法，只要不跳就一直在调用
       * @Date: 18:54 2021/2/1
       * @Param:
       * @return:
       */
      private boolean drop = true;
      public void jumpDown(List<Ground> groundList) {
              //一直下落
              vt = v0 + g * t;
              delta_height = v0 * t;
              v0 = vt;
              y += delta_height;
              //停止自由落体的判定
              for (int i = 0; i < groundList.size(); i++) {
                  Ground ground = groundList.get(i);
                  if (this.getRectangle().intersects(ground.getRectangle()) &&
                          this.y <= ground.y - this.height + 100) {
                      //停止自由落体
                      if (this.y >= ground.y - this.height) {
                          this.y = ground.y - this.height;
                          drop = false;
                          jump = false;
                          v0 = Constant.HERO_JUMP_SPEED;
                          vt = 0.0;
                          break;
                      }
                  } else {
                      drop = true;
                  }
              }


      }

       /**
        * @Author: 浅小北
        * @Description: 人物爬行的方法
        * @Date: 12:44 2021/2/2
        * @Param:
        * @return:
        */
       public boolean climb(List<Ground> groundList) {
           for (int i = 0; i < groundList.size(); i++) {
               Ground ground = groundList.get(i);
               if (this.getRectangle().intersects(ground.getRectangle())) {
                   return true;
               }
           }
           return false;
       }


      /**
       * @Author: 浅小北
       * @Description:  shoot方法，创建一个射击时长的变量 TODO
       * @Date: 17:37 2021/1/28
       * @Param:
       * @return:
       */
      private int shootCount = 0;
      private void shoot(){
          shootCount++;
          if (shootCount % 10 == 0) {
              MP -= 10;
              shoot = false;
              Arrow arrow;
              if (dir == Direction.LEFT) {
                  arrow = new Arrow(msc,x,y + this.height / 2,dir);
              } else {
                  arrow = new Arrow(msc,x,y + this.height / 2,dir);
              }
              msc.arrowList.add(arrow);
          }
      }

     /**
      * @Author: 浅小北
      * @Description: 根据当前人物的左右上下开关，确定方向和运动
      * @Date: 20:03 2021/1/27
      * @Param:
      * @return:
      */
     private void confirmStatus() {
         if (left && !right) {
             this.dir = Direction.LEFT;
             if (jump) {
                 this.action = Action.JUMP;
             }
         } else if (right && !left) {
             this.dir = Direction.RIGHT;
             if (jump) {
                 this.action = Action.JUMP;
             }
         } else if (jump) {
             this.action = Action.JUMP;
         } else if (down) {
             this.action = Action.PRONE;
         } else if (shoot) {
             this.action = Action.SHOOT;
         } else if (climb) {
             this.action = Action.CLIMB;
         } else {
             this.action = Action.STAND;
         }
     }
     
      /**
       * @Author: 浅小北
       * @Description: 按键的方法，按下
       * @Date: 20:21 2021/1/27
       * @Param:
       * @return:
       * @param e
       */
      public void keyPressed(KeyEvent e){
          switch (e.getKeyCode()) {
              case KeyEvent.VK_A:
                  left = true;
                  break;
              case KeyEvent.VK_D:
                  right = true;
                  break;
              case KeyEvent.VK_S:
                  down = true;
                  break;
              case KeyEvent.VK_K:
                  jump = true;
                  break;
              case KeyEvent.VK_J:
                  shoot = true;
                  break;
              case KeyEvent.VK_L:
                  pickUp = true;
                  break;
              case KeyEvent.VK_W:
                  climb = true;
                  break;
              default:
                  break;
          }
      }
       /**
        * @Author: 浅小北
        * @Description: 释放按键的方法
        * @Date: 20:29 2021/1/27
        * @Param:
        * @return:
        * @param
        */
       public void keyReleased(KeyEvent e) {
           switch (e.getKeyCode()) {
               case KeyEvent.VK_A:
                   left = false;
                   break;
               case KeyEvent.VK_D:
                   right = false;
                   break;
               case KeyEvent.VK_S:
                   down = false;
                   break;
               case KeyEvent.VK_L:
                   pickUp = false;
                   break;
               case KeyEvent.VK_W:
                   climb = false;
                   break;
               default:
                   break;
           }
       }

        /**
         * @Author: 浅小北
         * @Description: 人物捡道具的方法，人物和道具相交的时候捡起来
         * @Date: 18:44 2021/1/29
         * @Param:
         * @return:
         */
        private boolean pickUp(Prop prop){
            if (prop.live && this.getRectangle().intersects(prop.getRectangle())) {
                prop.live = false;
                for (int i = 0; i < msc.propPackage.props.size(); i++) {
                    Prop prop1 = msc.propPackage.props.get(i);
                    if (prop.type == prop1.type) {
                        prop1.quantity += 1;
                        return false;
                    }
                }
                msc.propPackage.props.add(prop);
                switch (prop.type) {
                    case 0:
                        this.HP += 50;
                        break;
                    case 1:
                        this.HP += 100;
                        break;
                    case 2:
                        this.HP += 300;
                        break;
                    case 3:
                        this.MP += 100;
                        break;
                    default:
                        break;
                }
                if (HP >= MAX_HP) {
                    HP = MAX_HP;
                }
                if (MP >= MAX_MP) {
                    MP = MAX_MP;
                }
            }
            return true;
        }

         /**
          * @Author: 浅小北
          * @Description: 捡道具的重载方法，负责遍历道具集合
          * @Date: 18:53 2021/1/29
          * @Param:
          * @return:
          */

         public boolean pickUp(List<Prop> propList) {
             for (int i = 0; i < propList.size(); i++) {
                 pickUp(propList.get(i));
             }
             return true;
         }


}
